package com.gjy.zk.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author gjy
 * @version 1.0
 * @since 2025-09-29 18:01:21
 */
@Slf4j
@Component
public class ZookeeperUtil {

    @Resource
    private CuratorFramework client;

    private final ExecutorService executor = Executors.newFixedThreadPool(4);

    /**
     * 创建持久节点
     */
    public String createPersistentNode(String path, String data) throws Exception {
        return client.create()
                .creatingParentsIfNeeded()
                .forPath(path, data.getBytes());
    }

    /**
     * 创建临时节点
     */
    public String createEphemeralNode(String path, String data) throws Exception {
        return client.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .forPath(path, data.getBytes());
    }

    /**
     * 创建顺序节点
     */
    public String createSequentialNode(String path, String data) throws Exception {
        return client.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT_SEQUENTIAL)
                .forPath(path, data.getBytes());
    }

    /**
     * 异步创建节点
     */
    public void createNodeAsync(String path, String data, CreateMode mode, BackgroundCallback callback) throws Exception {
        client.create()
                .creatingParentsIfNeeded()
                .withMode(mode)
                .inBackground(callback, executor)
                .forPath(path, data.getBytes());
    }

    /**
     * 检查节点是否存在
     */
    public boolean exists(String path) throws Exception {
        Stat stat = client.checkExists().forPath(path);
        return stat != null;
    }

    /**
     * 获取节点数据
     */
    public String getData(String path) throws Exception {
        byte[] data = client.getData().forPath(path);
        return data != null ? new String(data) : null;
    }

    /**
     * 获取节点数据并返回Stat信息
     */
    public String getDataWithStat(String path, Stat stat) throws Exception {
        byte[] data = client.getData().storingStatIn(stat).forPath(path);
        return data != null ? new String(data) : null;
    }

    /**
     * 设置节点数据
     */
    public Stat setData(String path, String data) throws Exception {
        return client.setData().forPath(path, data.getBytes());
    }

    /**
     * 设置节点数据（带版本号）
     */
    public Stat setDataWithVersion(String path, String data, int version) throws Exception {
        return client.setData().withVersion(version).forPath(path, data.getBytes());
    }

    /**
     * 删除节点
     */
    public void deleteNode(String path) throws Exception {
        client.delete().forPath(path);
    }

    /**
     * 强制删除节点（包括子节点）
     */
    public void deleteNodeForce(String path) throws Exception {
        client.delete().deletingChildrenIfNeeded().forPath(path);
    }

    /**
     * 获取子节点列表
     */
    public List<String> getChildren(String path) throws Exception {
        return client.getChildren().forPath(path);
    }

    /**
     * 监听节点变化
     */
    public void watchNode(String path) throws Exception {
        client.getData().watched().forPath(path);
    }

    /**
     * 监听子节点变化
     */
    public void watchChildren(String path) throws Exception {
        client.getChildren().watched().forPath(path);
    }

    /**
     * 获取节点状态信息
     */
    public Stat getStat(String path) throws Exception {
        return client.checkExists().forPath(path);
    }

    /**
     * 检查连接状态
     */
    public boolean isConnected() {
        return client.getZookeeperClient().isConnected();
    }

}
